﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Threading; // 线程
using System.Windows.Forms;

using System.Runtime.InteropServices;//  For Delay

namespace RobotCleaner
{
    public partial class RobotCleanerV1 : Form
    {
        public RobotCleanerV1()
        {
            InitializeComponent();
        }
        /// <summary>
        /// 机器人行走地图
        /// </summary>
        Map map = new Map();
        //=========================================
        //http://blog.csdn.net/suzilong11/article/details/7829093
        // Sep 15,2013 
        // by:EndlessRain
        // For:delay
        [DllImport("kernel32.dll")]

        static extern uint GetTickCount();

        static void Delay(uint ms)
        {
            uint start = GetTickCount();
            while (GetTickCount() - start < ms)
            {
                
            }
        }
        //==========================================
        //private Thread my_thread = new Thread(new ParameterizedThreadStart(RobotCleaner.Delay));
        #region 链表数据结构 
        // By   : EndlessRain
        // Date : Sep 15th,2013 Sunday 16:30
        // 保存 关键点的链表数据结构
        private List<Point> points = new List<Point>();
        /// <summary>
        /// 保存关键点的链表 初始化
        /// </summary>
        private void Points_ini()
        {
            points.Capacity = 100; // 初始链表容量
            points.Add(new Point(r.get_R_X(),r.get_R_Y())); // 增加初始化坐标点X,Y
        }
        #endregion
        #region 辅助函数 获取背景宽高
        /// <summary>
        /// 获取背景宽度
        /// </summary>
        /// <returns>宽</returns>
        private int GetPan_width()
        {
            int pan_width = this.panel1.Size.Width;
            return pan_width;
        }
        /// <summary>
        /// 获取背景高度
        /// </summary>
        /// <returns>高</returns>
        private int GetPan_height()
        {
            int pan_height = this.panel1.Size.Height;
            return pan_height;
        }
        #endregion
        #region 事件函数
        private void Clean_Click(object sender, EventArgs e)
        {
            ////测试
            //MessageBox.Show( "初始坐标："+
            //                 "("+points[0].X.ToString() +
            //                 ","+ points[0].Y.ToString()+")");
            timer1.Enabled = true;
            //my_while();
        }
        private void my_while()
        {
            while (true)
            {
                //回型清扫
                robotCleanClockwise();
                //输出调试参数
                output_debug();
                Delay( 10 );
            }
        }
        private void RobotCleaner_Resize(object sender, EventArgs e)
        {
            // this.panel1.set = this.Size.Width - this.panel1.Location.X;
        }
        private void RobotCleaner_Load(object sender, EventArgs e)
        {
            // 获取时间间隔
            timer1.Interval = r.R_Time;
            // 初始化Point链表
            Points_ini();

            // 初始 可清理区域坐标
            r.Area_CanClean = new Point(panel1.Size.Width, 0);

            // 初始化机器人行走地图
            map.Map_Init(this.panel1);

            // 初始化可清理区域坐标
            map.Map_AddWallPoint(new Point(r.get_R_X(),r.get_R_Y()));
        }
        private void panel1_Paint(object sender, PaintEventArgs e)
        {

            //Graphics g = panel1.CreateGraphics();
            ////g.FillEllipse(new SolidBrush(r.R_Path_Color), 10, 10, 60, 60);

            ////g.DrawLine(new Pen(Color.White), new Point(10, 10), new Point(610, 10));
            ////g.DrawLine(new Pen(Color.White), new Point(10, 10), new Point(10, 410));
            ////g.DrawLine(new Pen(Color.White), new Point(610, 10), new Point(610, 410));
            ////g.DrawLine(new Pen(Color.White), new Point(10, 410), new Point(610, 410));
            //for (int j = 1; j < Convert.ToInt32((GetPan_width() / 10)); j++)
            //{
            //    g.DrawLine(new Pen(Color.Red), new Point(20 * j, 0), new Point(20 * j, (GetPan_height() / 10) * 10));
            //}
            //for (int i = 1; i < Convert.ToInt32((GetPan_height() / 10)); i++)
            //{
            //    g.DrawLine(new Pen(Color.Red), new Point(0, 20 * i), new Point((GetPan_width() / 10) * 10, 20 * i));
            //}
            ////  //g.DrawRectangle(new Pen(r.R_Center_Color), 100, 50, 80, 40);
            ////  g.FillEllipse(new SolidBrush(r.R_Center_Color),
            ////this.pictureBox1.Location.X, this.pictureBox1.Location.X + 500,
            ////this.pictureBox1.Location.Y, this.pictureBox1.Location.Y + 500);
           
        }
        private void timer1_Tick(object sender, EventArgs e)
        {
            label2.Text = map.CleanAreaPoint.Count.ToString();
            /*
            if (this.pictureBox1.Right < this.panel1.Width)
            {
                this.pictureBox1.Location = new Point(this.pictureBox1.Location.X + 5, this.pictureBox1.Location.Y);
                //this.label2.Location = new Point(this.label2.Location.X + 100,this.label2.Location.Y);
            }
            else
            {
                this.pictureBox1.Location = new Point(this.pictureBox1.Location.X - 5, this.pictureBox1.Location.Y);
                //this.pictureBox1.Location.X = 10;
                //this.label2.Location = new Point(this.label2.Location.X - 100, this.label2.Location.Y);
            }
            this.richTxb_robotinfo.Text += "\nrobot:X:" + this.pictureBox1.Location.X +
                                           "\nrobot:Y:" + this.pictureBox1.Location.Y;
            Graphics g = panel1.CreateGraphics();
            //g.DrawRectangle(new Pen(r.R_Center_Color), 10, 10, 60, 60);
            //g.FillEllipse(new SolidBrush(r.R_Center_Color), 10, 10, 60, 60);
            g.FillEllipse(new SolidBrush(r.R_Center_Color),
                pictureBox1.Location.X + 10, this.pictureBox1.Location.X + 10,
                this.pictureBox1.Location.X + 50, this.pictureBox1.Location.Y + 50);
            //g.FillEllipse(new SolidBrush(r.R_Center_Color),
            //    this.pictureBox1.Location.X, this.pictureBox1.Location.X + 500,
            //    this.pictureBox1.Location.Y, this.pictureBox1.Location.Y + 500);

            //Graphics g = this.panel1.CreateGraphics();
            ////g.FillEllipse(new SolidBrush, );
            ////Robot r = new Robot();
            ////r.R_Height;
            ////r.R_Width;

            //Point center = new Point(100, 100);
            //int r = 20;
            //Rectangle rect = new Rectangle(center.X - r, center.Y - r, center.X + r, center.Y + r);
            //g.DrawEllipse(Pens.Red, rect);
             */
            //回型清扫
            robotCleanClockwise();
            //输出调试参数
            output_debug();
            //Invalidate();
            //测试绘制圆函数
            //testCircle();
        }
        private void testCircle()
        {
            Graphics g = panel1.CreateGraphics();
            g.DrawEllipse(new Pen(r.R_Center_Color),270,10,330,330);
        }
        private void Pause_Click(object sender, EventArgs e)
        {
            timer1.Enabled = false;
        }
        private void button1_Click(object sender, EventArgs e)
        {
            //Graphics g = this.panel1.CreateGraphics();
            //g.FillEllipse(new SolidBrush(r.R_Center_Color),
            //   pictureBox1.Location.X, this.pictureBox1.Location.X + 500,
            //   this.pictureBox1.Location.Y, this.pictureBox1.Location.Y + 500);
        }
        #endregion
        #region 输出调试信息
        /// <summary>
        /// 输出调试参数
        /// </summary>
        /// <returns></returns>
        private void output_debug()
        {

            this.richTxb_robotinfo.Text += "Robot: Wid:" + this.r.R_Width.ToString() +
                                           "\nRobot: Hei:" + this.r.R_Height.ToString() + "\n" +
                                           "R_X:" + r.get_R_X() +
                                           "\nR_Y:" + r.get_R_Y() + "\n\n" +
                                           "=====================" +
                                           r.get_R_X().ToString() + ":" +
                                           r.get_R_Y().ToString() + "\n" +
                                           Convert.ToString(r.get_R_X() + r.R_Width) + ":" +
                                           Convert.ToString(r.get_R_Y() + r.R_Height) + "\n" +
                                           "dir:"+r.get_direction()+
                                           "=====================\n";
        }
        #endregion 
        #region 全局机器人变量
        //创建 一个机器人
        Robot r = new Robot();
        #endregion
        #region 清扫算法
        /// <summary>
        /// 机器人 清扫地面 顺时针回型
        /// </summary>
        private void robotCleanClockwise()
        {
            switch (r.get_direction())
            {
                case 1:
                    //顺时针右
                    right();
                    break;
                case 2:
                    //顺时针下
                    down();
                    break;
                case 3:
                    //顺时针左
                    left();
                    break;
                case 4:
                    //顺时针上
                    up();
                    break;
                case 5:
                    //逆时针右
                    _right();
                    break;
                case 6:
                    //逆时针下
                    _down();
                    break;
                case 7:
                    //逆时针左
                    _left();
                    break;
                case 8:
                    //逆时针上
                    _up();
                    break;
                default:
                    break;
            }
            //Graphics g = panel1.CreateGraphics();
            //if (r.get_direction() == 1)
            //{
            //    if (r.get_R_X() + r.R_Width < panel1.Size.Width)
            //    {
            //        //Graphics g = panel1.CreateGraphics();
            //        g.FillEllipse(new SolidBrush(r.R_Path_Color),
            //                             r.get_R_X(), r.get_R_Y(),
            //                             r.R_Width, r.R_Height);
            //        r.set_R_X(10);
            //        if (r.get_R_X() + r.R_Width >= panel1.Size.Width)
            //        {
            //            r.set_R_X(-10);
            //            r.set_direction(2);
            //            return;
            //        }
            //    }
            //}
            //else if (r.get_direction() == 2)
            //{
            //    if (r.get_R_Y() + r.R_Height < panel1.Size.Height)
            //    {
            //        //Graphics g = panel1.CreateGraphics();
            //        g.FillEllipse(new SolidBrush(r.R_Path_Color),
            //                             r.get_R_X(), r.get_R_Y(),
            //                             r.R_Width, r.R_Height);
            //        r.set_R_Y(10);
            //        if (r.get_R_Y() + r.R_Height >= panel1.Size.Height)
            //        {
            //            r.set_R_Y(-10);
            //            return;
            //        }
            //    }
            //}
            //if (r.get_R_X()+r.R_Width > panel1.Size.Width )
            //{

            //}
            //r.set_R_Y(20);
            //g.DrawEllipse(new Pen(r.R_Path_Color),
            //                     r.get_R_X(), r.get_R_Y(),
            //                     r.R_Width, r.R_Height);
            //g.DrawRectangle(new Pen(r.R_Center_Color),
            //                     r.get_R_X(), r.get_R_Y(),
            //                     r.R_Width,  r.R_Height);

        }
        #endregion 
        #region 画轨迹
        /// <summary>
        /// 画机器人路线轨迹
        /// </summary>
        private void drawEllipse()
        {
            try
            {
                using (Graphics g = panel1.CreateGraphics())
                {
                    //g.FillEllipse(new SolidBrush(r.R_Path_Color),
                    //                     r.get_R_X(), r.get_R_Y(),
                    //                     r.R_Width, r.R_Height);

                    //g.FillEllipse(new SolidBrush(r.R_Center_Color),
                    //                     r.get_R_X() + r.R_Width / 3, r.get_R_Y() + r.R_Height / 3,
                    //                     r.R_Width / 3, r.R_Height / 3);
                    g.DrawEllipse(new Pen(r.R_Path_Color),
                                         r.get_R_X(), r.get_R_Y(),
                                         r.R_Width, r.R_Height);
                    g.DrawEllipse(new Pen(r.R_Center_Color),
                                         r.get_R_X() + r.R_Width / 3, r.get_R_Y() + r.R_Height / 3,
                                         r.R_Width / 3, r.R_Height / 3);
                }
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message);
            }
        }
        #endregion 
        #region 机器人顺时针方向移动
        /// <summary>
        /// 机器人顺时针向右移动
        /// </summary>
        private void right()
        {
            int temp_width = panel1.Size.Width;
            // 如果没有原点节点 增加一个
            if (map.CleanAreaPoint.Count < 1)
            {
                map.CleanAreaPoint.Add(new Point(r.get_R_X(), r.get_R_Y() + r.R_Height - r.Ini_R_Y));
                // debug
                this.richTextBox1.Text += "Point1：(" + r.get_R_X() + "," + r.get_R_Y() + ")";
            }
            // 模拟寻找右边墙壁过程
            if (r.get_R_X() + r.R_Width < panel1.Size.Width)
            {
                drawEllipse();           // 画轨迹
                r.set_R_X(r.get_step()); // 增加步长
                // 第一次记录下右上方节点
                if (map.CleanAreaPoint.Count < 2 && r.get_R_X() + r.R_Width >= temp_width)
                {
                    map.CleanAreaPoint.Add(new Point(r.get_R_X() + r.Ini_R_X, r.get_R_Y() + r.R_Height));
                    // debug
                    this.richTextBox1.Text += "\nPoint2：(" + (r.get_R_X() - r.R_Width).ToString()
                                              + "," + (r.get_R_Y() + r.R_Height).ToString() + ")";
                }
                if (map.CleanAreaPoint.Count >= 4)
                {
                    //MessageBox.Show("map.CleanAreaPoint.Count >= 4");
                    temp_width = map.CleanAreaPoint[map.CleanAreaPoint.Count - 3].X;
                }
                if (r.get_R_X() + r.R_Width >= temp_width)
                {
                    if (map.CleanAreaPoint.Count >= 4)
                    {
                         map.CleanAreaPoint.Add(new Point(r.get_R_X(), r.get_R_Y()));
                    }
                    if (map.CleanAreaPoint.Count <= 4)
                    {
////////////////////////////////////////////////////////////////////
                    r.set_R_X(-r.get_step());
/////////////////////////////////////////////////////////////////////
                    }
                    // 如果不是已绕一周
                    // 增加可清理区域坐标
                    //map.Map_AddCleanAreaPoint(new Point(r.get_R_X() - r.R_Width, r.get_R_Y()));
                    // 改变方向为下
                    //MessageBox.Show("r.set_direction(2);");
                    r.set_direction(2);
                    this.richTextBox1.Text += "\n改变方向:下";
                    // 如果 墙角坐标空
                    //if (points.Count == 1)
                    //{
                    //    //points.Add(new Point(r.get_R_X() - r.R_Width, r.get_R_Y()));
                    //    //r.set_Area_CanClean_A2_( r.get_R_X() );
                    //}
                }
            }
        }
        /// <summary>
        /// 机器人顺时针向下移动
        /// </summary>
        private void down()
        {
            int temp_Height = panel1.Size.Height;
            if (r.get_R_Y() + r.R_Height < panel1.Size.Height)
            {
                drawEllipse();   //画轨迹
                r.set_R_Y(r.get_step());
                if (map.CleanAreaPoint.Count < 3 && r.get_R_Y() + r.R_Height >= temp_Height)
                {
                    map.CleanAreaPoint.Add(new Point(r.get_R_X(), r.get_R_Y()));
                    // debug
                    this.richTextBox1.Text += "\nPoint3：(" + r.get_R_X()
                                              + "," + r.get_R_Y() + ")";
                }
                if (map.CleanAreaPoint.Count >= 4)
                {
                    temp_Height = map.CleanAreaPoint[map.CleanAreaPoint.Count - 4].Y;
                    //temp_Height = temp_Height;
                    //MessageBox.Show(temp_Height.ToString()); 
                }
                if (r.get_R_Y() + r.R_Height >= temp_Height)
                {
                    if (map.CleanAreaPoint.Count >= 4)
                    {
                        map.CleanAreaPoint.Add(new Point(r.get_R_X(), r.get_R_Y() ));
                    }
                    r.set_R_Y(-r.get_step());
                    // 改变方向为左
                    this.richTextBox1.Text += "\n改变方向:左";
                    r.set_direction(3);
                }
            }
        }
        /// <summary>
        /// 机器人顺时针向左移动
        /// </summary>
        private void left()
        {
            int left = 0;
            if (map.CleanAreaPoint.Count >= 4)
            {
                left = map.CleanAreaPoint[map.CleanAreaPoint.Count - 4].X;
                //MessageBox.Show(left.ToString() + (map.CleanAreaPoint.Count - 2).ToString());
            }
            if (r.get_R_X() > left)
            {
                drawEllipse();   //画轨迹
                r.set_R_X(-r.get_step());
                if (r.get_R_X() <= left)
                {
                    if (map.CleanAreaPoint.Count < 4)
                    {
                        map.CleanAreaPoint.Add(new Point(r.get_R_X() + r.R_Width,r.get_R_Y()));
                        // debug
                        this.richTextBox1.Text += "\nPoint4：(" + r.get_R_X()
                                                  + "," + r.get_R_Y() + ")";
                    }
                    else
                    {
                        map.CleanAreaPoint.Add(new Point(r.get_R_X() + r.R_Width, r.get_R_Y()));
                    }
                    r.set_R_X(r.get_step());
                    // 改变方向为上
                    r.set_direction(4);
                    this.richTextBox1.Text += "\n改变方向:上";
                    //// 记录下此时的坐标 X, Y
                    //points.Add(new Point(r.get_R_X(), r.get_R_Y()));
                    
                }
            }
        }
        /// <summary>
        /// 机器人顺时针向上移动
        /// </summary>
        private void up()
        {
            int up = 0;
            //if (map.CleanAreaPoint.Count > 4 && r.get_R_Y() <= map.CleanAreaPoint[map.CleanAreaPoint.Count - 3].Y)
            //{
            //    map.CleanAreaPoint.Add(new Point(r.get_R_X() + r.R_Width, r.get_R_Y() + r.R_Height));
            //    // debug
            //    this.richTextBox1.Text += "\nPoint5：(" + r.get_R_X()
            //                              + "," + r.get_R_Y() + ")";
            //}
            if (map.CleanAreaPoint.Count >= 4)
            {
                up = map.CleanAreaPoint[map.CleanAreaPoint.Count - 4].Y;
            }
            if (r.get_R_Y() > up )
            {
                drawEllipse();   //画轨迹
                r.set_R_Y(-r.get_step());
                if (r.get_R_Y() <= up)
                {
                    r.set_R_Y(r.get_step());
                    // 改变方向为右
                    if (r.get_R_Y() <= map.CleanAreaPoint[map.CleanAreaPoint.Count - 4].Y)
                    {
                        MessageBox.Show("===========");
                        map.CleanAreaPoint.Add(new Point(r.get_R_X() /*+ r.R_Width*/, r.get_R_Y() + r.R_Height));
                    }
                    if (map.CleanAreaPoint.Count >= 4)
                    {
                        map.CleanAreaPoint.Add(new Point(r.get_R_X() /*+ r.R_Width*/, r.get_R_Y() + r.R_Height /*- r.Ini_R_Y / 3*/ ));
                    }
                    r.set_direction(1);
                    this.richTextBox1.Text += "\n改变方向:右";
                    //// 记录下此时的坐标 X, Y
                    //points.Add(new Point(r.get_R_X(), r.get_R_Y()));

                }
            }
            //// 判断两个点距离是否小于等于直径
            //if (IsLessDiameter(new Point(r.get_R_X(), r.get_R_Y()), points[0]))
            //{
            //    r.set_direction(1);
            //}
        }
        #endregion 
        #region 机器人逆时针方向移动
        /// <summary>
        /// 机器人逆时针向右移动
        /// </summary>
        private void _right()
        {
            if (r.get_R_X() + r.R_Width < panel1.Size.Width)
            {
                drawEllipse();   //画轨迹
                r.set_R_X(r.get_step());
                if (r.get_R_X() + r.R_Width >= panel1.Size.Width)
                {
                    r.set_R_X(-r.get_step());
                    r.set_direction(8);
                    return;
                }
            }
        }
        /// <summary>
        /// 机器人逆时针向下移动
        /// </summary>
        private void _down()
        {
            if (r.get_R_Y() + r.R_Height < panel1.Size.Height)
            {
                drawEllipse();   //画轨迹
                r.set_R_Y(r.get_step());
                if (r.get_R_Y() + r.R_Height >= panel1.Size.Height)
                {
                    r.set_R_Y(-r.get_step());
                    r.set_direction(5);
                    return;
                }
            }
        }
        /// <summary>
        /// 机器人逆时针向左移动
        /// </summary>
        private void _left()
        {
            if (r.get_R_X() > 0)
            {
                drawEllipse();   //画轨迹
                r.set_R_X(-r.get_step());
                if (r.get_R_X() <= 0)
                {
                    r.set_R_X(r.get_step());
                    r.set_direction(6);
                    return;
                }
            }
        }
        /// <summary>
        /// 机器人逆时针向上移动
        /// </summary>
        private void _up()
        {
            if (r.get_R_Y() > 0)
            {
                drawEllipse();   //画轨迹
                r.set_R_Y(-r.get_step());
                if (r.get_R_Y() <= 0)
                {
                    r.set_R_Y(r.get_step());
                    r.set_direction(7);
                    return;
                }
            }
        }
        #endregion

        /// <summary>
        /// 是否小于等于直径
        /// </summary>
        /// <param name="_p1">点1</param>
        /// <param name="_p2">点2</param>
        /// <returns></returns>
        private bool IsLessDiameter(Point _p1, Point _p2)
        {
            int delta_x = _p1.X - _p2.X;
            int delta_y = _p1.Y - _p2.Y;
            if (delta_x * delta_x + delta_y * delta_y <= r.R_Width*r.R_Width)
            {
                return true;
            }
            return false;
        }

        private void RobotCleaner_FormClosed(object sender, FormClosedEventArgs e)
        {
            Application.Exit();
        }
    }
}